package jmine.tec.services.execution;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.SortedMap;
import java.util.TreeMap;

import jmine.tec.services.api.Service;
import jmine.tec.services.api.ServiceExecutionException;
import jmine.tec.services.api.ServiceValidationExecutionException;
import jmine.tec.services.api.ServicesPage;
import jmine.tec.services.api.execution.ExecutorParams;
import jmine.tec.services.api.execution.ExecutorTransactionPolicy;

/**
 * @author takeshi
 */
public class SimulatedServicesPageExecutor extends BaseServicesPageExecutor {

    /**
     * {@inheritDoc}
     */
    @Override
    protected SortedMap<Integer, Throwable> doExecuteServices(List<Service<?>> services) {
        SortedMap<Integer, Throwable> outcome = new TreeMap<Integer, Throwable>();
        ListIterator<Service<?>> it = services.listIterator();
        while (it.hasNext()) {
            Service<?> service = it.next();
            try {
                this.executeService(services, service);
                this.getExecutionLogController().getSessionFactory().getCurrentSession().flush();
                this.getExecutionLogController().getSessionFactory().getCurrentSession().clear();
            } catch (ServiceValidationExecutionException e) {
                outcome.put(it.previousIndex(), e);
            } catch (ServiceExecutionException e) {
                outcome.put(it.previousIndex(), e);
            }
        }
        return outcome;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean rollbackNeeded(List<Service<?>> services, SortedMap<Integer, ?> outcome) {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean isAbortExecution(List<Service<?>> services, SortedMap<Integer, ?> outcome, ExecutorParams params) {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<List<Service<?>>> getServiceBlocks(List<ServicesPage> pages, ExecutorTransactionPolicy policy) {
        List<List<Service<?>>> blocks = new ArrayList<List<Service<?>>>(pages.size());
        for (ServicesPage servicesPage : pages) {
            List<Service<?>> services = servicesPage.getServices();
            for (Service<?> service : services) {
                blocks.add(Collections.<Service<?>> singletonList(service));
            }
        }
        return blocks;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void logServiceBlockExecution(List<Service<?>> services, SortedMap<Integer, Throwable> outcome) {
        for (int i = 0; i < services.size(); i++) {
            Throwable t = outcome.get(i);
            final Service<?> service = services.get(i);
            if (t == null) {
                this.logNotExecuted(service, MSG_ROLLEDBACK);
            } else {
                this.logErrorExecution(service, t.getMessage(), t);
            }
        }
    }

}
